package com.ouwen.smartpay.facadeimpl.openapi;

import com.alibaba.dubbo.config.annotation.Service;
import com.fm.core.utils.enums.ResultStatus;
import com.ouwen.smartpay.openapi.api.ServiceFacade;
import com.ouwen.smartpay.openapi.order.ServiceOrder;
import com.ouwen.smartpay.openapi.result.ServiceResult;
import com.ouwen.smartpay.service.chain.context.Context;
import com.ouwen.smartpay.service.chain.slotchain.SlotChainProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author <a href="http://youngitman.tech">青年IT男</a>
 * @version v1.0.0
 * @className ServiceFacadeImpl
 * @description 统一支付接入服务接口实现 注意：由于Openapi上层包装了一层转换成所有这里不暴露为RPC对外服务
 * @JunitTest: {@link  }
 * @date 2020-04-22 11:53
 **/
@Service(version = "1.0.0")
public class ServiceFacadeImpl implements ServiceFacade {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public ServiceResult service(ServiceOrder order) {

        ServiceResult result = new ServiceResult();

        try {

            process(order, result);

        } catch (Throwable e) {

            logger.error("统一网关入口处理未知异常:", e);

            result.setStatus(ResultStatus.processing);

            result.setCode(ResultStatus.processing.code());

            result.setDescription("未知异常,请重试业务");

        }

        return result;

    }

    public void process(ServiceOrder order, ServiceResult result) throws Throwable {

        //构建调用链
        buildChain(order, result);

    }

    /***
     *
     * 处理链路构建和调用
     *
     * @author liyong
     * @date 15:23 2020-04-24
     * @param order
     * @exception
     * @return void
     **/
    private void buildChain(ServiceOrder order, ServiceResult result) throws Throwable {

        //构建传递上下文
        Context context = Context.builder()
                .service(order.getService())
                .partnerId(order.getPartnerId())
                .subPartnerId(order.getSubPartnerId())
                .requestNo(order.getRequestNo())
                .build();

        //开始前置处理直到成功返回
        SlotChainProvider.newSlotChain().entry(context, order, result);

    }
}
